package core;

import log.LogInfo;
import log.Logger;
import request.Request;
import response.CGIResponse;
import response.Response;
import response.StaticResponse;
import utils.TimeUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Handler implements Runnable {
    private final Socket socket;

    private LogInfo getLogInfo(Request request, Response response) {
        LogInfo logInfo = new LogInfo();
        logInfo.setSourceIp(socket.getInetAddress().toString().substring(1));
        logInfo.setSourceIdentity("");
        logInfo.setId("");
        logInfo.setTimeStamp(TimeUtils.now());
        logInfo.setMethod(request.getMethod());
        logInfo.setRequestedResource(request.getResource());
        logInfo.setStatusCode(response.getStatusCode());
        logInfo.setSize(response.getContentSize());
        logInfo.setReferer(request.get("Referer"));

        return logInfo;
    }

    public Handler(Socket socket) {
        this.socket = socket;
    }

    public void run() {
        try {
            InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream();

            Request request = Request.parseFromInputStream(inputStream);

            if (request.isError()) {
                socket.close();
                return;
            }
            Response response;
            if (request.getResource().endsWith("cgi")) {
                response = CGIResponse.response(request);
            } else {
                response = StaticResponse.response(request);
            }

            LogInfo logInfo = getLogInfo(request, response);
            Logger.log(logInfo);

            if (request.getMethod().equals("HEAD")) {
                outputStream.write(response.head().getBytes());
            } else {
                outputStream.write(response.compact().getBytes());
            }

            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
